perm filename RECOG3.SAI[SYS,HE] blob sn#021171 filedate 1973-01-20 generic text, type T, neo UTF8
COMMENT ⊗   VALID 00020 PAGES 
RECORD PAGE   DESCRIPTION
 00001 00001	   VALID 00020 PAGES 
 00003 00002	ENTRY DUMMY
 00005 00003	α	BOUNDED
 00008 00004	α	MIDPOINT
 00009 00005	α	SAMELINE
 00011 00006	α	IMAGINARY
 00013 00007	α	L1DOTL2XL3
 00017 00008	α	VERT_PLANE_PT
 00019 00009	α	HORIZ_PLANE_PT
 00021 00010	α	FIND4PTS - CASE 1
 00024 00011	α	FIND4PTS - CASE 2
 00026 00012	α	FIND4PTS - CASE 3
 00029 00013	α	FIND4PTS - CASE 4
 00031 00014	α	FIND4PTS - CASE 5
 00033 00015	α	FIND4PTS - CASE 6
 00035 00016	α	FIND4PTS + CASE 7
 00038 00017	α	FINDMATCH
 00041 00018		   α	FINDMATCH - LOOP
 00044 00019		   α	FINDMATCH - CHAIN, PEAK
 00049 00020				 α	FINDMATCH + FINISH
 00054 ENDMK
⊗;
ENTRY DUMMY;

BEGIN "RECOG3"

REQUIRE		250	PNAMES;
REQUIRE	"PREAMB.SAI[SYS,HE]"	SOURCE_FILE;
REQUIRE	"CPXSYM.AUX[SYS,HE]"	SOURCE_FILE;
REQUIRE	"RECDPY.HDR[SYS,HE]"	SOURCE_FILE;
REQUIRE	"RECCOM.AUX[SYS,HE]"	SOURCE_FILE;

α LOCALS;
INTEGER FLAG,ERRFLAG;

α EXTERNAL PROCEDURES;
ERP		SQRT(REAL X);

ERP	ANGLE(SAFE REAL ARRAY ITEMVAR P1,P2,P3;INTEGER N);
EP	CROSS_PROD(REFERENCE SAFE REAL ARRAY A,B,CP);
EBP	DIST(SAFE REAL ARRAY ITEMVAR P1,P2);
ERP	DOT_PROD(SAFE REAL ARRAY V1,V2);
ESP	GENSYM(INTEGER ITEMVAR X);
EP	MATCHLINES(ITEMVAR F,MF,L1,L2,ML1,ML2);
EBP	PARALLEL(ITEMVAR L1,L2);
ESP	PRINTNAME(ITEMVAR X);
EBP	SUBSET1(SET ES1,ES2);
EBP	VERT(ITEMVAR E);

α	BOUNDED
this procedure was stolen from LOU.
I make no claims as to its behavior!;

INTERNAL BOOLEAN PROCEDURE BOUNDED(REAL X,Y;SAFE REAL ARRAY P;INTEGER N);
	BEGIN "BOUNDED"
	   INTEGER I,C,N2,II;
	   REAL M1,M2,RV,RH;
	   LABEL NEXTL,ADD4;

	   C←0;
	   FOR I←N STEP 2 UNTIL 2*(N-1) DO
	    BEGIN "B1"
	       RV←(P[(I+1) MOD N]-Y)*(Y-P[(I+3) MOD N]);
	       IF RV<0.0
		THEN GO TO NEXTL;
	       IF RV> 0.0
		THEN BEGIN
		   RH←(P[I MOD N]-X)*(X-P[(I+2) MOD N]);
		   IF RH < 0.0
		    THEN BEGIN
		       C←IF X<P[I MOD N] THEN C+1 ELSE C;
		       GO TO NEXTL
		    END;
		   IF RH>0.0
		    THEN BEGIN
		       M1←(P[(I+1) MOD N]-P[(I+3) MOD N])/
			(P[I MOD N]-P[(I+2) MOD N]);
		       M2←(	IF P[(I+1) MOD N]>P[(I+3) MOD N]
			THEN (P[(I+1) MOD N]-Y)/(P[I MOD N]-X)
			 ELSE (P[(I+3) MOD N]-Y)/(P[(I+2) MOD N]-X));
		       IF M1=M2
			THEN RETURN (TRUE);
		       C←IF M1>M2 THEN C+1 ELSE C;
		       GO TO NEXTL
		    END;
		   IF P[I MOD N]=P[(I+2) MOD N]
		    THEN RETURN (TRUE);
		   IF P[I MOD N]=X
		    THEN BEGIN
		       C←	IF X<P[(I+2) MOD N]
			THEN C+1
			 ELSE C
		    END
		    ELSE	C←IF X<P[I MOD N] THEN C+1 ELSE C;
		   GO TO NEXTL
		END;
	       IF P[(I+1) MOD N]=P[(I+3) MOD N]
		THEN BEGIN
		   IF (P[I MOD N]-X)*(X-P[(I+2) MOD N])≥0.0
		    THEN RETURN (TRUE)
		     ELSE GO TO NEXTL;
		END;
	       II← IF Y=P[(I+1) MOD N] THEN I ELSE I+2;
	       IF X>P[II MOD N]
		THEN GO TO ADD4;
	       IF X<P[II MOD N]
		THEN BEGIN
		   C←	IF (P[(II+3) MOD N]-P[(II+1) MOD N])*
		    (P[(II+1) MOD N]-P[(II-1) MOD N])>0.0
		     THEN C+1
		      ELSE C;
		   GO TO ADD4
		END;
	       RETURN (TRUE);
	    ADD4:	I←I+2;
	    NEXTL:
	    END "B1";
	   RETURN(	IF C  MOD 2 =1
	    THEN TRUE
	     ELSE FALSE)
	END "BOUNDED";

α	MIDPOINT
returns an item that is the midpoint of a line.;

INTERNAL SAFE REAL ARRAY ITEMVAR PROCEDURE MIDPOINT(ITEMVAR L);
	BEGIN "MIDPOINT"
	   SAFE REAL ARRAY ITEMVAR U,V,M;
	   SET S;
	   α	S←DENDPT⊗L;
	   U←LOP(S);
	   V←COP(S);

	M←NEW(SIZE3);

	   ∂(M)[1]←0.5*(∂(U)[1]+∂(V)[1]);
	   ∂(M)[2]←0.5*(∂(U)[2]+∂(V)[2]);
	   ∂(M)[3]←1.0;

	   RETURN(M);
	END "MIDPOINT";

α	SAMELINE;

INTERNAL BOOLEAN PROCEDURE SAMELINE(ITEMVAR OE,PE);
	BEGIN "SAMELINE"
	   REAL ARRAY ITEMVAR MOE,MPE,OE1,OE2,PE1,PE2;
	   SET S1;
	   REAL DIST1;

TYPE "SAMELINE - ENTERED" EOM;

	   S1←ENDPT⊗OE;
	   OE1←LOP(S1);
	   OE2←COP(S1);
	   PE1←LOP(S1);
	   PE2←COP(S1);

	   S1←PHI;
	   DIST1←ABS(DIST(OE1,OE2)-DIST(PE1,PE2));
	   IF DIST1>DIST(OE1,OE2)/SAME1	 ∨ DIST1>DIST(PE1,PE2)/SAME1
	    THEN BEGIN
	       TYPE TAB&"LENGTHS TOO DISSIMILAR. "&PRINTNAME(OE)&
		"  "&PRINTNAME(PE)&"  "&
		 CVG(ABS(DIST(OE1,OE2)-DIST(PE1,PE2))) EOM;
	       RETURN (FALSE);
	    END;

	   IF ¬PARALLEL (OE,PE)
	    THEN  BEGIN
	       TYPE TAB&"EDGES "&PRINTNAME(OE)&" AND "&
		PRINTNAME(PE)&" NOT PARALLEL ENOUGH." EOM;
	       ERASE ENDPT⊗PE≡ANY;
	       RETURN (FALSE);
	    END;
	   ERASE ENDPT⊗PE≡ANY;


	   MOE←MIDPOINT(OE);
	   MPE←MIDPOINT(PE);

	   DIST1←DIST(MOE,MPE);
	   DELETE(MOE);
	   DELETE (MPE);

	   IF DIST1>SAME2
	    THEN BEGIN
	       TYPE TAB&PRINTNAME(OE)&" AND "&PRINTNAME(PE)&
		" TOO FAR APART. "&CVG(DIST1) EOM;
	       RETURN (FALSE);
	    END;
	   RETURN (TRUE);
	END "SAMELINE";

α	IMAGINARY
Returns an "IMAGINARY" prototype point that
can be matched with a "T-JOINT POINT" on the body viewed.
The point returned is at a distance DIST from point P
along line L in the model.;

INTERNAL REAL ARRAY ITEMVAR PROCEDURE IMAGINARY
	 (SAFE REAL ARRAY ITEMVAR P;REAL ITEMVAR L;REAL DIST);
	BEGIN "IMAGINARY"
	   INTEGER I;
	STRING STR;
	   SAFE REAL ARRAY ITEMVAR X,PP;
	   REAL MAG;
	   SAFE REAL ARRAY V[1:3];

	   X←COP(GLB ENDPT⊗L-{P});
	   FOR I←1 S1U 3 DO
	    V[I]←GLB ∂(X)[I]-GLB ∂(P)[I];
	   MAG←SQRT(V[1]↑2+V[2]↑2+V[3]↑2);
	   STR←GENSYM(IPOINT);
	   PP←NEW(SIZE5);NEW_PNAME(PP,STR);
	   FOR I←1 S1U 3 DO
	    GLB ∂(PP)[I]←(V[I]/MAG)*DIST + GLB ∂(P)[I];
	   RETURN (PP);

	END "IMAGINARY";

α	L1DOTL2XL3
check that L1.(L2 X L3) is the same for
the model and the projection.
;

INTERNAL BOOLEAN PROCEDURE L1DOTL2XL3(SAFE REAL ARRAY ITEMVAR U,V,W);
BEGIN "L1DOTL2XL3"
	   SAFE REAL ARRAY ITEMVAR MV1,MV2,MV3,MV4;
	   INTEGER I;
	   SAFE REAL ARRAY CP,MCP,VL1,VL2,VL3,VL4,MVL1,MVL2,MVL3,MVL4[1:3];
	   REAL DP,MDP;

	   TYPE "L1DOTL2XL3 - ENTERED" EOM;
	   TYPE TAB&PRINTNAME(U)&"  "&PRINTNAME(V)&"  "&PRINTNAME(W) EOM;
	   IF KIND=CHAIN
	    THEN BEGIN "CHAIN"
	       ;α bless our parser;
	       ASSIGN MV3 | GLB ENDPT⊗U≡MV3 ∧ GLB ENDPT⊗V≡MV3 HOLDS;
	       ASSIGN MV2 | GLB ENDPT⊗V≡MV2 ∧ GLB ENDPT⊗W≡MV2 HOLDS;
	       MV1←COP((GLB ENDPT⊗W)-{MV2});
	       MV4←COP((GLB ENDPT⊗U)-{MV3});

	       FOR I←1 S1U 3 DO
		BEGIN "CHAIN2"
		   ;α bless our parser;
		   MVL1[I]←GLB ∂(MV4)[I]-GLB ∂(MV3)[I];
		   MVL2[I]←GLB ∂(MV3)[I]-GLB ∂(MV2)[I];
		   MVL3[I]←GLB ∂(MV1)[I]-GLB ∂(MV2)[I];
		   VL1[I]←∂(V4)[I+2]-∂(V3)[I+2];
		   VL2[I]←∂(V3)[I+2]-∂(V2)[I+2];
		   VL3[I]←∂(V1)[I+2]-∂(V2)[I+2];
		END "CHAIN2";
	    END "CHAIN";
	   IF KIND=PEAK
	    THEN BEGIN "PEAK"
	       ;α bless our parser;
	       ASSIGN MV2| GLB ENDPT⊗U≡MV2 ∧ GLB ENDPT⊗V≡MV2 HOLDS;
	       MV1←COP((GLB ENDPT⊗V)-{MV2});
	       MV3←COP((GLB ENDPT⊗W)-{MV2});
	       MV4←COP((GLB ENDPT⊗U)-{MV2});

	       FOR I←1 S1U 3 DO
		BEGIN "PEAK2"
		   ;α bless our parser;
		   MVL1[I]←GLB ∂(MV4)[I]-GLB ∂(MV2)[I];
		   MVL2[I]←GLB ∂(MV1)[I]-GLB ∂(MV2)[I];
		   MVL3[I]←GLB ∂(MV3)[I]-GLB ∂(MV2)[I];
		   VL1[I]←∂(V4)[I+2]-∂(V2)[I+2];
		   VL2[I]←∂(V1)[I+2]-∂(V2)[I+2];
		   VL3[I]←∂(V3)[I+2]-∂(V2)[I+2];
		END "PEAK2";
	    END "PEAK";

	   CROSS_PROD(MVL2,MVL3,MCP);
	   CROSS_PROD(VL2,VL3,CP);
	   MDP←DOT_PROD(MCP,MVL1);
	   DP←DOT_PROD(CP,VL1);
	   TYPE TAB&"DP="&CVG(DP)&"  MDP="&CVG(MDP)&↓&
	   	TAB&"CP="&CVG(CP[1])&"  "&CVG(CP[2])&"  "&CVG(CP[3])&↓&
		TAB&"MCP="&CVG(MCP[1])&"  "&CVG(MCP[2])&"  "&CVG(MCP[3]) EOM;
	   IF DP*MDP>0.0
	    THEN RETURN (TRUE)
	     ELSE RETURN (FALSE);
	END "L1DOTL2XL3";

α	VERT_PLANE_PT
	 T,B1,B2 are image vertices.
	  T lies off the table in a plane normal to the
	   table which passes thru B1 and B2.
	    returns with 3-d coords stuffed in T
	     ;

INTERNAL PROCEDURE VERT_PLANE_PT(SAFE REAL ARRAY ITEM T,B1,B2);
	BEGIN "VERTPPT"
	   REAL M,B,DX,T1,XT,YT;

	   TYPE "VERT_PLANE_PT - ENTERED" EOM;
	   IF ∂(T)[5]>∂(B1)[5]
	    THEN RETURN;
	   TYPE TAB&PRINTNAME(V1)&" "&PRINTNAME(V2)&" "&PRINTNAME(V3)&" "&
	    PRINTNAME(V4) EOM;
	   DX←∂(B2)[3]-∂(B1)[3];
	   M←(∂(B2)[4]-∂(B1)[4])/DX;
	   B←(∂(B2)[3]*∂(B1)[4]-∂(B1)[3]*∂(B2)[4])/DX;
	   XT←∂(T)[3];
	   YT←∂(T)[4];
	   T1←(M*XT-YT+B)/(LENS_REC[2]-YT-M*(LENS_REC[1]-XT));
	   ∂(T)[3]←T1*LENS_REC[1]+(1.0-T1)*XT;
	   ∂(T)[4]←T1*LENS_REC[2]+(1.0-T1)*YT;
	   ∂(T)[5]←T1*LENS_REC[3]+(1.0-T1)*∂(T)[5];
	   RETURN;
	END "VERTPPT";


α	HORIZ_PLANE_PT
	 U is an unknown image point lying in the same plane parallel to
	  the table as K, a point whose 3-d coords are known.
	   returns with 3-d coords of U properly stuffed in.
	    ;

INTERNAL PROCEDURE HORIZ_PLANE_PT(SAFE REAL ARRAY ITEM U,K);
	BEGIN "HORIZPPT"
	   REAL H,HZC;
	   TYPE "HORIZ_PLANE_PT - ENTERED" EOM;
	   IF ∂(U)[5]=∂(K)[5]
	    THEN RETURN;
	   TYPE TAB&PRINTNAME(V1)&" "&PRINTNAME(V2)&" "&PRINTNAME(V3)&" "&
	    PRINTNAME(V4) EOM;
	   H←∂(K)[5];
	   HZC←(H-∂(U)[5])/(LENS_REC[3]-∂(U)[5]);
	   ∂(U)[3]←HZC*LENS_REC[1]+∂(U)[3]*(1.0-HZC);
	   ∂(U)[4]←HZC*LENS_REC[2]+∂(U)[4]*(1.0-HZC);
	   ∂(U)[5]←H;
	   RETURN;
	END "HORIZPPT";

α	FIND4PTS - CASE 1
	 set global itemvars V1,V2,V3 and V4 and lines L1,L2, and
	  L3 to 4 points, and their associated 3 lines on body B.
	   KIND is a global variable set to "CHAIN" if the
	    edges are connected in a chain or "PEAK" if the
	     edges meet at a common point.
	      M is the model to which body B corresponds.
	       ;

INTERNAL PROCEDURE FIND4PTS(ITEMVAR B,M);
	BEGIN "FIND4PTS"
	   SET ITEMVAR X;
	   REAL ITEMVAR Y,L,LA,F,SORET,LONG;
	   BOOLEAN BOOL1;
	SET ITEMVAR BS;
	   SET S;
	   INTEGER I,N,NP,NM;
	   REAL LEN;
	   LABEL CASE1,CASE2,CASE3,CASE4,CASE5,CASE6,CASE7;

TYPE "FIND4PTS - ENTERED" EOM;
DPYLAB("LOOKING FOR CASE 1.");

ASSIGN X|BASE⊗B≡X HOLDS;
ASSIGN BS|EXTERIOR⊗B≡BS HOLDS;
IF LENGTH(∂(X))=1
THEN GO TO CASE4;
CASE1:
∀ L|Lε∂(X) DO
 ∀ V2|ENDPT⊗L≡V2 DO
BEGIN "CASE1"
	LABEL LEND1;
	IF LENGTH(ENDPT`V2∩LINE⊗B)=3
	THEN BEGIN
		BOOL1←TRUE;
		∀ LA|ENDPT⊗LA≡V2 ∧ LINE⊗B≡LA DO
			IF ∂(LA)≤0
			THEN BOOL1←FALSE;
		IF ¬BOOL1
		THEN GO TO LEND1;
		ASSIGN L1|ENDPT⊗L1≡V2 ∧ LINE⊗B≡L1 ∧ (¬(L1ε∂(BS)))
		     HOLDS;
		V4←COP(ENDPT⊗L1-{V2});
		S←ENDPT`V2∩LINE⊗B;
		REMOVE L1 FROM S;
		L2←LOP(S);
		L3←COP(S);
		V1←COP(ENDPT⊗L2-{V2});
		V3←COP(ENDPT⊗L3-{V2});
		IF ∂(V1)[1]>∂(V3)[1]
		THEN BEGIN
			L2↔L3;
			V1↔V3;
			END;
		IF ∂(V1)[2]>∂(V2)[2] ∧ ∂(V3)[2]>∂(V2)[2]
		THEN BEGIN
			KIND←PEAK;
			S←PHI;
			RETURN;
			END;
		 END;
LEND1:
	END "CASE1";

α	FIND4PTS - CASE 2
	    ;

DPYLAB( "LOOKING FOR CASE 2." );

CASE2:
∀ L|Lε∂(X) DO
 ∀ V2|ENDPT⊗L≡V2 DO
BEGIN "CASE2"
	LABEL LABX,LEND2;
	S←PHI;
	∀ LA|ENDPT⊗LA≡V2 ∧ LINE⊗B≡LA DO
		IF ∂(LA)<0
		THEN GO TO LEND2;
	∀ LA|ENDPT⊗LA≡V2 ∧ LINE⊗B≡LA ∧ (∂(LA)>0) DO
		PUT LA IN S;
	IF LENGTH(S)≠2
	THEN GO TO LEND2;
	L2←LOP(S);
	L3←COP(S);
	V3←COP(ENDPT⊗L2-{V2});
	V1←COP(ENDPT⊗L3-{V2});
	S←ENDPT`V3∩LINE⊗B-{L2};
	N←0;
	∀ LA|LAεS ∧ (∂(LA)>0) DO
	BEGIN	L1←LA;
		N←N+1;
		END;
	IF N=1
	THEN BEGIN
		V4←COP(ENDPT⊗L1-{V3});
		GO TO LABX;
		END;
	S←ENDPT`V1∩LINE⊗B-{L3};
	N←0;
	∀ LA|LAεS ∧ (∂(LA)>0) DO
	BEGIN	L1←LA;
		N←N+1;
		END;
	IF N=1
	THEN BEGIN
		V4←COP(ENDPT⊗L1-{V1});
		L2↔L3;
		V1↔V3;
		END;
	IF N=0
	THEN GO TO LEND2;
LABX:
	IF ¬VERT(L1) ∨ {L1,L2,L3}≤∂(X)
	THEN GO TO LEND2;
	IF ∂(V1)[2]>∂(V2)[2] ∧ ∂(V3)[2]>∂(V2)[2]
	THEN BEGIN
		KIND←CHAIN;
		S←PHI;
		RETURN;
		END;
LEND2:
	END "CASE2";

α	FIND4PTS - CASE 3
	    ;

DPYLAB("LOOKING FOR CASE 3.");

CASE3:
∀ L|Lε∂(X) DO
 ∀ V2|ENDPT⊗L≡V2 DO
BEGIN "CASE3"
	LABEL LEND3;
	S←PHI;
	∀ LA|ENDPT⊗LA≡V2 ∧LINE⊗B≡LA  ∧ (∂(LA)>0) DO
		PUT LA IN S;
	IF LENGTH(S)≠2	∨ LENGTH(ENDPT`V2∩LINE⊗B)≠3
	THEN GO TO LEND3;
	L1←COP(ENDPT`V2∩LINE⊗B-S);
	IF ∂(L1)<0
	THEN GO TO LEND3;
	V4←COP(ENDPT⊗L1-{V2});
	L2←LOP(S);
	L3←COP(S);
	V1←COP(ENDPT⊗L2-{V2});
	V3←COP(ENDPT⊗L3-{V2});
	IF ∂(V1)[1]>∂(V3)[1]
	THEN BEGIN
		V1↔V3;
		L2↔L3;
		END;
	FOR I←1 S1U 3 DO SIZE3[I]←∂(V4)[I+2];
	VERT_PLANE_PT(V4,V2,V1);
	LEN←0;
	FOR I←3 S1U 5 DO
		LEN←LEN+(∂(V4)[I]-∂(V2)[I])↑2;
	LEN←SQRT(LEN);
	TYPE TAB&"ASSUMING PLANE V1,V2,V4 IS VERTICAL." EOM;
	TYPE TAB&CVG(LEN) EOM;
	IF LENGTH(ENDPT`V4∩LINE⊗B)=1
	THEN GO TO LEND3
	ELSE ∂(L1)←LEN;
	IF SUBSET1({L1},EDGE⊗M)
	THEN BEGIN
		KIND←PEAK;
		S←PHI;
		RETURN;
		END;
	FOR I←1 S1U 3 DO ∂(V4)[I+2]←SIZE3[I];
	VERT_PLANE_PT(V4,V2,V3);
	LEN←0;
	FOR I←3 S1U 5 DO
		LEN←LEN+(∂(V4)[I]-∂(V2)[I])↑2;
	LEN←SQRT(LEN);
	TYPE TAB&"ASSUMING PLANE V2,V3,V4 IS VERTICAL." EOM;
	TYPE TAB&CVG(LEN) EOM;
	IF LENGTH(ENDPT`V4∩LINE⊗B)=1
	THEN GO TO LEND3
	ELSE ∂(L1)←LEN;
	IF SUBSET1({L1},EDGE⊗M)
	THEN BEGIN
		KIND←PEAK;
		S←PHI;
		RETURN;
		END
	ELSE BEGIN
		TYPE TAB&"SCREWUP NO. 1 IN MATCHING PROCESS." EOM;
		S←PHI;
		RETURN;
		END;
LEND3:
	END "CASE3";

α	FIND4PTS - CASE 4
	    ;

DPYLAB( "LOOKING FOR CASE 4." );

CASE4:
∀ L1,L2|LINE⊗B≡L1 ∧ (¬L1εVERTICALS) ∧ L2εVERTICALS ∧
	(L1≠L2) ∧ ADJ(L1,L2) ∧ (∂(L1)>0 ∧ ∂(L2)>0) DO
BEGIN "CASE4"
	LABEL LABY,LEND4;
	TYPE TAB&"L1 IS "&PRINTNAME(L1)&" AND L2 IS "&PRINTNAME(L2) EOM;
	ASSIGN V3|ENDPT⊗L1≡V3 ∧ ENDPT⊗L2≡V3 HOLDS;
	TYPE TAB&"V3 IS "&PRINTNAME(V3) EOM;
	V4←COP(ENDPT⊗L1-{V3});
	V2←COP(ENDPT⊗L2-{V3});
	IF ∂(V3)[7]>∂(V2)[7]
	THEN GO TO LEND4;
	TYPE TAB&"THIS POINT NOW." EOM;
	ASSIGN F| FACE⊗B≡F ∧ BOUNDARY⊗F≡L1 ∧ BOUNDARY⊗F≡L2 HOLDS;
	TYPE TAB&"NOW AT HERE" EOM;
	∀ L3|ENDPT⊗L3≡V2 ∧ LINE⊗B≡L3  ∧ (¬(BOUNDARY⊗F≡L3)) DO
		GO TO LABY;
	GO TO LEND4;
LABY:
	V1←COP(ENDPT⊗L3-{V2});
	IF LENGTH(ENDPT`V1∩LINE⊗B)=1
	THEN GO TO LEND4;
	HORIZ_PLANE_PT(V1,V2);
	LEN←0;
	FOR I←3 S1U 5 DO
		LEN←LEN+(∂(V1)[I]-∂(V2)[I])↑2;
	∂(L3)←SQRT(LEN);
	IF SUBSET1({L3},EDGE⊗M)
	THEN BEGIN
		KIND←CHAIN;
		S←PHI;
		RETURN;
		END
	ELSE BEGIN
		TYPE TAB&"SCREWUP NO. 2 IN MATCHING PROCESS." EOM;
		S←PHI;
		RETURN;
		END;
LEND4:
	END "CASE4";

α	FIND4PTS - CASE 5
	    ;

DPYLAB( "LOOKING FOR CASE 5.");

CASE5:
∀ L|Lε∂(X) DO
 ∀ V2|ENDPT⊗L≡V2 DO
BEGIN "CASE5"
	LABEL LEND5;
	IF LENGTH(ENDPT`V2∩LINE⊗B)=3
	THEN BEGIN
		NP←NM←0;
		∀ LA|ENDPT⊗LA≡V2 ∧ LINE⊗B≡LA  DO
		IF ∂(LA)<0
		THEN BEGIN
			SORET←LA;
			NM←NM+1;
			END
		ELSE IF ∂(LA)>0
		     THEN NP←NP+1;
		IF NP≠2 ∨ NM≠1
		THEN GO TO LEND5;
		ASSIGN L1|ENDPT⊗L1≡V2 ∧ LINE⊗B≡L1 ∧ (¬(L1ε∂(BS)))
			HOLDS;
		V4←COP(ENDPT⊗L1-{V2});
		S←ENDPT`V2∩LINE⊗B;
		REMOVE L1 FROM S;
		L2←LOP(S);
		L3←COP(S);
		V1←COP(ENDPT⊗L2-{V2});
		V3←COP(ENDPT⊗L3-{V2});
		IF ∂(V1)[1]>∂(V3)[1]
		THEN BEGIN
			L2↔L3;
			V1↔V3;
			END;
		IF SORET=L1
		THEN MAKE STATUS⊗L1≡OCCLUDED
		ELSE IF SORET=L2
		     THEN MAKE STATUS⊗L2≡OCCLUDED
		     ELSE MAKE STATUS⊗L3≡OCCLUDED;
		IF ∂(V1)[2]>∂(V2)[2] ∧ ∂(V3)[2]>∂(V2)[2]
		THEN BEGIN
			KIND←PEAK;
			S←PHI;
			RETURN;
			END;
		 END;
LEND5:
	END "CASE5";

α	FIND4PTS - CASE 6
	    ;

DPYLAB( "LOOKING FOR CASE 6." );

CASE6:
∀ L|Lε∂(X) DO
 ∀ V3|ENDPT⊗L≡V3 DO
BEGIN "CASE6"
	LABEL LEND6;
	IF LENGTH(ENDPT`V3∩LINE⊗B)≠1
	THEN BEGIN
		LABEL LABA;
		NP←NM←0;
		∀ LA|ENDPT⊗LA≡V3 ∧ LINE⊗B≡LA  DO
		IF ∂(LA)<0
		THEN BEGIN
			PUT LA IN S;
			NM←NM+1;
			END
		ELSE IF ∂(LA)>0
		     THEN BEGIN
				NP←NP+1;
				LONG←LA;
				END;
		IF NP≠1  ∨ ¬VERT(LONG)
		THEN GO TO LEND6;
		L2←LONG;
		L1←L;
		V4←COP(ENDPT⊗L1-{V3});
		V2←COP(ENDPT⊗L2-{V3});
		ASSIGN F|BOUNDARY⊗F≡L1 ∧ BOUNDARY⊗F≡L2 HOLDS;
		ASSIGN L3|ENDPT⊗L3≡V2 ∧ LINE⊗B≡L3 ∧ (¬(BOUNDARY⊗F≡L3))
			HOLDS;
		V1←COP(ENDPT⊗L3-{V2});
		IF LENGTH(ENDPT`V1∩LINE⊗B)=1
		THEN GO TO LEND6;
		HORIZ_PLANE_PT(V1,V2);
		LEN←0;
		FOR I←3 S1U 5 DO
			LEN←LEN+(∂(V1)[I]-∂(V2)[I])↑2;
		∂(L3)←SQRT(LEN);
		IF SUBSET1({L3},EDGE⊗M)
		THEN GO TO LABA
		ELSE BEGIN
			TYPE TAB&"SCREWUP NO. 3 IN MATCHING PROCESS." EOM;
			S←PHI;
			RETURN;
			END;
LABA:
		MAKE STATUS⊗L1≡OCCLUDED;
		KIND←CHAIN;
		S←PHI;
		RETURN;
		END;
LEND6:
	END "CASE6";

α	FIND4PTS + CASE 7
	    ;

DPYLAB( "LOOKING FOR CASE 7." );

CASE7:
∀ L|Lε∂(X) DO
 ∀ V2|ENDPT⊗L≡V2 DO
BEGIN "CASE7"
	LABEL LEND7;
	IF LENGTH(ENDPT`V2∩LINE⊗B)=3
	THEN BEGIN
		LABEL LABB;
		NP←NM←0; S←PHI;
		∀ LA|ENDPT⊗LA≡V2 ∧ LINE⊗B≡LA DO
		IF ∂(LA)>0
		THEN NP←NP+1
		ELSE IF ∂(LA)<0
		     THEN BEGIN
			SORET←LA;
			NM←NM+1;
			END
		     ELSE L1←LA;
		IF NP≠1 ∨ NM≠1
		THEN GO TO LEND7;
		S←ENDPT`V2∩LINE⊗B-{L1};
		V4←COP(ENDPT⊗L1-{V2});
		L2←LOP(S);
		L3←COP(S);
		V1←COP(ENDPT⊗L2-{V2});
		V3←COP(ENDPT⊗L3-{V2});
		IF ∂(V1)[1]>∂(V3)[1]
		THEN BEGIN
			V1↔V3;
			L1↔L3;
			END;
		VERT_PLANE_PT(V4,V1,V2);
		LEN←0;
		FOR I←3 S1U 5 DO
			LEN←LEN+(∂(V4)[I]-∂(V2)[I])↑2;
		LEN←SQRT(LEN);
		IF LENGTH(ENDPT`V4∩LINE⊗B)=1
		THEN GO TO LEND7
		ELSE ∂(L1)←LEN;
		IF SUBSET1({L1},EDGE⊗M)
		THEN GO TO LABB;
		VERT_PLANE_PT(V4,V2,V3);
		LEN←0;
		FOR I←3 S1U 5 DO
		LEN←LEN+(∂(V4)[I]-∂(V2)[I])↑2;
		LEN←SQRT(LEN);
		IF LENGTH(ENDPT`V4∩LINE⊗B)=1
		THEN GO TO LEND7
		ELSE ∂(L1)←LEN;
		IF ¬SUBSET1({L1},EDGE⊗M)
		THEN BEGIN
			TYPE TAB&"SCREWUP NO. 4 IN MATCHING PROCESS." EOM;
			S←PHI;
			RETURN;
			END;
LABB:
		IF SORET=L2
		THEN MAKE STATUS⊗L2≡OCCLUDED
		ELSE MAKE STATUS⊗L3≡OCCLUDED;
		KIND←PEAK;
		S←PHI;
		RETURN;
		END;
LEND7:
	END "CASE7";

END "FIND4PTS";

α	FINDMATCH
	 finds 4 points, MV1,MV2,MV3, and MV4, on prototype that
	  correspond to V1,V2,V3, and V4 on the body under
	   consideration.
	    There itemvars are all global.
	     ;

INTERNAL BOOLEAN PROCEDURE FINDMATCH(ITEMVAR PROTOTYPE,B);
	BEGIN "FINDMATCH"
	   REAL ITEMVAR E;
	   REAL ANGP,ANGM;
	   SET SL1,SL2,SL3,SL1S,SL2S,SL3S;
	   REAL	 ITEMVAR U,V,W,X;
	   LABEL OUT1,OUT2,LOOP;
	   ITEMVAR F12,MF12,F13,MF13,FA,MF,MFA;
	   SET S1,S2,MATCHED;
	   ITEMVAR ML,C,R,ML1,ML2,MR,F23,MF23;
	   BOOLEAN BOOL;
	   REAL ITEMVAR LA,L,LB;

TYPE "FINDMATCH - ENTERED" EOM;
	   MATCHED←SL1←SL2←SL3←PHI;
	   SL1S←SL2S←SL3S←PHI;
	   ∀ E|GLB EDGE⊗PROTOTYPE≡E DO
	    BEGIN "FM1"
	       ;α bless our parser;
	       IF ∂(L1)>0
		THEN IF ABS(∂(L1)-GLB ∂(E)) <
		 (IF GLB ∂(E) < FINDM1
		  THEN FINDM2
		   ELSE GLB ∂(E)/FINDM3 )
		    THEN PUT E IN SL1;
	       IF ∂(L1)<0
		THEN IF GLB ∂(E) > ABS(∂(L1))
		 THEN PUT E IN SL1;
	       IF ∂(L2)>0
		THEN IF ABS(∂(L2) - GLB ∂(E)) <
		 (IF (GLB ∂(E)) < FINDM1
		  THEN FINDM2
		   ELSE GLB ∂(E) / FINDM3)
		    THEN PUT E IN SL2;
	       IF ∂(L2)<0
		THEN IF GLB ∂(E)>ABS(∂(L2))
		 THEN PUT E IN SL2;
	       IF ∂(L3)>0
		THEN IF ABS(∂(L3)-GLB ∂(E)) <
		 (IF GLB ∂(E)<FINDM1
		  THEN FINDM2
		   ELSE GLB ∂(E)/FINDM3)
		    THEN PUT E IN SL3;
	       IF ∂(L3)<0
		THEN IF GLB ∂(E)>ABS(∂(L3))
		 THEN PUT E IN SL3;
	    END "FM1";
	   α	FINDMATCH - LOOP
	    ;

DPYTELL("FINDMATCH - LOOP");
	LOOP:
	   TYPE TAB&"LOOPING" EOM;
	   IF SL1=PHI ∨ SL2=PHI ∨ SL3=PHI
	    THEN BEGIN
	       TYPE
		TAB&"NO MODEL EDGES OF RIGHT LENGTH FOUND DURING MATCHING PROCESS."
		 EOM;
	       SL1←SL2←SL3←SL1S←SL2S←SL3S←S1←S2←MATCHED←PHI;
	       RETURN(FALSE);
	    END;
	   BOOL←FALSE;
	   LA←COP(SL1);
	   ∀ LB|LBεSL1 DO
	    IF GLB ∂(LB)≠GLB ∂(LA)
	     THEN BEGIN
		BOOL←TRUE;
		DONE;
	     END;
	   IF BOOL
	    THEN BEGIN
	       ;
	       IF ABS(GLB ∂(LA)-∂(L1))<ABS(GLB ∂(LB)-∂(L1))
		THEN L←LA
		 ELSE  L←LB;
	       ∀ LA|LAεSL1 ∧ (GLB ∂(LA)≠GLB ∂(L)) DO
		BEGIN
		   REMOVE LA FROM SL1;
		   PUT LA IN SL1S;
		END;
	    END;

	   BOOL←FALSE; LA←COP(SL2);
	   ∀ LB|LBεSL2 DO
	    IF GLB ∂(LB)≠GLB ∂(LA)
	     THEN BEGIN
		BOOL←TRUE;
		DONE;
	     END;
	   IF BOOL
	    THEN BEGIN
	       ;
	       IF ABS(GLB ∂(LA)-∂(L2))<ABS(GLB ∂(LB)-∂(L2))
		THEN L←LA
		 ELSE  L←LB;
	       ∀ LA|LAεSL2 ∧ (GLB ∂(LA)≠GLB ∂(L)) DO
		BEGIN
		   REMOVE LA FROM SL2;
		   PUT LA IN SL2S;
		END;
	    END;

	   BOOL←FALSE;
	   LA←COP(SL3);
	   ∀ LB|LBεSL3 DO
	    IF GLB ∂(LB)≠GLB ∂(LA)
	     THEN BEGIN
		BOOL←TRUE;
		DONE;
	     END;
	   IF BOOL
	    THEN BEGIN
	       ;
	       IF ABS(GLB ∂(LA)-∂(L3))<ABS(GLB ∂(LB)-∂(L3))
		THEN L←LA
		 ELSE  L←LB;
	       ∀ LA|LAεSL3 ∧ (GLB ∂(LA)≠GLB ∂(L)) DO
		BEGIN
		   REMOVE LA FROM SL3;
		   PUT LA IN SL3S;
		END;
	    END;

	   α	FINDMATCH - CHAIN, PEAK
	    ;

	   TYPE TAB&"LENGTHS L1,L2,L3= "&CVG(∂(L1))&" "&
	    CVG(∂(L2))&" "&CVG(∂(L3)) EOM;
	   TYPE TAB&"NO. IN SL1,SL2,SL3= "&CVG(LENGTH(SL1))&" "&
	    CVG(LENGTH(SL2))&" "&CVG(LENGTH(SL3)) EOM;

DPYLAB("FINDMATCH - CHAIN.");
	   IF KIND=CHAIN
	    THEN BEGIN "CHAIN"
	       ∀ U,V,W| UεSL1 ∧ VεSL2 ∧ WεSL3 ∧
		(U≠V ∧ U≠W ∧ V≠W) ∧
		 GADJ(U,V) ∧ GADJ(V,W) ∧ (¬GADJ(U,W)) DO
		  IF L1DOTL2XL3(U,V,W)
		   THEN BEGIN "CHAINLOOP"
		      LABEL CHAINLOOP;
		      MV2←COP(GLB ENDPT⊗V ∩ GLB ENDPT⊗W);
		      MV3←COP(GLB ENDPT⊗U ∩ GLB ENDPT⊗V);
		      IF ¬(STATUS⊗L1≡OCCLUDED)
		       THEN MV4←COP(GLB ENDPT⊗U-{MV3})
			ELSE MV4←IMAGINARY(MV3,U,ABS(∂(L1)));
		      IF ¬(STATUS⊗L3≡OCCLUDED)
		       THEN MV1←COP(GLB ENDPT⊗W-{MV2})
			ELSE MV1←IMAGINARY(MV2,W,ABS(∂(L3)));
		      ANGP←ANGLE(V1,V2,V3,3);
		      ANGM←ANGLE(MV1,MV2,MV3,4);
		      TYPE TAB&"ANGP="&CVG(ANGP)&" ANGM="&CVG(ANGM) EOM;
		      IF ABS(ANGP-ANGM) > FINDM4
		       THEN GO TO CHAINLOOP;
		      ANGP←ANGLE(V2,V3,V4,3);
		      ANGM←ANGLE(MV2,MV3,MV4,4);
		      TYPE TAB&"ANGP="&CVG(ANGP)&" ANGM="&CVG(ANGM) EOM;
		      IF ABS(ANGP-ANGM)>FINDM4
		       THEN GO TO CHAINLOOP;
		      ANGP←ANGLE(V1,V2,V4,3);
		      ANGM←ANGLE(MV1,MV2,MV4,4);
		      TYPE TAB&"ANGP="&CVG(ANGP)&" ANGM="&CVG(ANGM) EOM;
		      IF ABS(ANGP-ANGM)>FINDM4
		       THEN GO TO CHAINLOOP;

		      ASSIGN F12|FACE⊗B≡F12 ∧ BOUNDARY⊗F12≡L1 ∧ BOUNDARY⊗
		       F12≡L2 HOLDS;
		      ASSIGN MF12| GLB FACE⊗PROTOTYPE≡MF12 ∧ GLB BOUNDARY⊗
		       MF12≡U ∧
			GLB BOUNDARY⊗MF12≡V HOLDS;
		      MAKE MATCH⊗F12≡MF12;
		      PUT F12 IN MATCHED;

		      F23←NIL;
		      ∀ FA|FACE⊗B≡FA  ∧	 BOUNDARY⊗FA≡L2 ∧ BOUNDARY⊗FA≡L3 DO
		       BEGIN
			  F23←FA;
			  DONE;
		       END;
		      IF F23≠NIL
		       THEN BEGIN
			  ;
			  ASSIGN MF23|	GLB FACE⊗PROTOTYPE≡MF23 ∧
			   GLB BOUNDARY⊗MF23≡V ∧
			    GLB BOUNDARY⊗MF23≡W HOLDS;
			  MAKE MATCH⊗F23≡MF23;
			  PUT F23 IN MATCHED;
			  BOOL←TRUE;
			  GO TO OUT1;
		       END;

		      FA←COP(CORNER`V2∩FACE⊗B-{F12});
		      ASSIGN MF|GLB FACE⊗PROTOTYPE≡MF ∧
		       GLB BOUNDARY⊗MF≡V ∧ GLB BOUNDARY⊗MF≡W HOLDS;
		      MFA←COP(GLB CORNER`MV2-{MF,MF12});
		      MAKE MATCH⊗FA≡MFA;
		      PUT FA IN MATCHED;
		      BOOL←FALSE;
		      GO TO OUT1;
		   CHAINLOOP:
		   END "CHAINLOOP";
	       GO TO OUT2;
	    END "CHAIN"
	    ELSE IF KIND=PEAK
	     THEN BEGIN "PEAK"
		;
DPYLAB("FINDMATCH - PEAK.");
		∀ U,V,W|	UεSL1 ∧ VεSL2 ∧ WεSL3 ∧
		 (U≠V ∧ U≠W ∧ V≠W) ∧
		  GADJ(U,V) ∧ GADJ(V,W) ∧ GADJ(U,W) DO
		   ∀ X|$ VERTEX⊗PROTOTYPE≡X DO
		    IF $ (ENDPT`X)={U,V,W}
		     THEN IF L1DOTL2XL3(U,V,W)
		      THEN BEGIN "PEAKLOOP"
			 LABEL PEAKLOOP;

			 α	FINDMATCH + FINISH
			  ;
			 TYPE TAB&"L1DOTL2XL3 OK THIS PEAK." EOM;
			 MV2←X;
			 IF ¬(STATUS⊗L1≡OCCLUDED)
			  THEN MV4←COP(GLB ENDPT⊗U-{MV2})
			   ELSE MV4←IMAGINARY(MV2,U,ABS(∂(L1)));
			 IF ¬(STATUS⊗L2≡OCCLUDED)
			  THEN MV1←COP(GLB ENDPT⊗V-{MV2})
			   ELSE MV1←IMAGINARY(MV2,V,ABS(∂(L2)));
			 IF ¬(STATUS⊗L3≡OCCLUDED)
			  THEN MV3←COP(GLB ENDPT⊗W-{MV2})
			   ELSE MV3←IMAGINARY(MV2,W,ABS(∂(L3)));
			 ANGP←ANGLE(V1,V2,V4,3);
			 ANGM←ANGLE(MV1,MV2,MV4,4);
			 IF ABS(ANGP-ANGM)>FINDM4
			  THEN GO TO PEAKLOOP;
			 ANGP←ANGLE(V4,V2,V3,3);
			 ANGM←ANGLE(MV4,MV2,MV3,4);
			 IF ABS(ANGP-ANGM)>FINDM4
			  THEN GO TO PEAKLOOP;
			 ANGP←ANGLE(V1,V2,V3,3);
			 ANGM←ANGLE(MV1,MV2,MV3,4);
			 IF ABS(ANGP-ANGM)>FINDM4
			  THEN GO TO PEAKLOOP;
			 ASSIGN F12|	FACE⊗B≡F12 ∧
			  BOUNDARY⊗F12≡L1 ∧
			   BOUNDARY⊗F12≡L2 HOLDS;
			 ASSIGN MF12|	GLB FACE⊗PROTOTYPE≡MF12 ∧
			  GLB BOUNDARY⊗MF12≡U ∧
			   GLB BOUNDARY⊗MF12≡V HOLDS;
			 MAKE MATCH⊗F12≡MF12;
			 PUT F12 IN MATCHED;

			 ASSIGN F13|	FACE⊗B≡F13 ∧
			  BOUNDARY⊗F13≡L1 ∧
			   BOUNDARY⊗F13≡L3 HOLDS;
			 ASSIGN MF13|	GLB FACE⊗PROTOTYPE≡MF13 ∧
			  GLB BOUNDARY⊗MF13≡U ∧
			   GLB BOUNDARY⊗MF13≡W HOLDS;
			 MAKE MATCH⊗F13≡MF13;
			 PUT F13 IN MATCHED;
			 GO TO OUT1;
		      PEAKLOOP:
		      END "PEAKLOOP";
		GO TO OUT2;
	     END "PEAK";

DPYLAB("FINDMATCH- OUT1");
	OUT1:
	   MAKE MATCH⊗L1≡U;
	   MAKE MATCH⊗L2≡V;
	   MAKE MATCH⊗L3≡W;

	   TYPE TAB&"LENGTHS U,V,W= "&CVG(GLB ∂(U))&
	    " "&CVG(GLB ∂(V))&" "&CVG(GLB ∂(W)) EOM;
	   MATCHLINES(F12,MF12,L1,L2,U,V);
	   IF KIND=PEAK
	    THEN MATCHLINES(F13,MF13,L1,L3,U,W)
	     ELSE IF BOOL
	      THEN MATCHLINES(F23,MF23,L2,L3,V,W)
	       ELSE BEGIN
		  L←COP(BOUNDARY⊗F12∩BOUNDARY⊗FA);
		  ML←COP(MATCH⊗L);
		  MATCHLINES(FA,MFA,L,L3,ML,W);
	       END;

DPYLAB("FINDMATCH - FINISH.");
	   TYPE TAB&"FINISH MATCHING. " EOM;
	   ∀ C| POINT⊗B≡C ∧ (LENGTH(CORNER`C∩FACE⊗B)=3) ∧
	    (LENGTH(CORNER`C∩FACE⊗B∩MATCHED)=2) DO
	     BEGIN	"FINISH"
		TYPE TAB&PRINTNAME(C) EOM;
		S1←CORNER`C∩FACE⊗B;
		S2←S1∩MATCHED;
		R←COP(S1-S2);
		ASSIGN U,V|	ENDPT⊗U≡C ∧ ENDPT⊗V≡C ∧ (U≠V) ∧
		 BOUNDARY⊗R≡U ∧ BOUNDARY⊗R≡V HOLDS;
		TYPE  TAB&PRINTNAME(U)&"  "&PRINTNAME(V) EOM;
		ML1←COP(MATCH⊗U);
		ML2←COP(MATCH⊗V);
		ASSIGN MR|	GLB BOUNDARY⊗MR≡ML1 ∧
		 GLB BOUNDARY⊗MR≡ML2 HOLDS;
		MAKE MATCH⊗R≡MR;
		PUT R IN MATCHED;
		MATCHLINES(R,MR,U,V,ML1,ML2);
	     END "FINISH";
	   SL1←SL2←SL3←SL1S←SL2S←SL3S←S1←S2←MATCHED←PHI;
	   RETURN(TRUE);

DPYLAB("FINDMATCH - OUT2");
	OUT2:
	   IF SL1S=PHI ∧ SL2S=PHI
	    THEN BEGIN "OUT"
	       TYPE TAB&"FAILURE IN MATCHING PROCESS." EOM;
	       SL1←SL2←SL3←SL1S←SL2S←SL3S←S1←S2←MATCHED←PHI;
	       RETURN (FALSE);
	    END "OUT";
	   IF SL1S≠PHI THEN SL1←SL1S;SL1S←PHI;
	   IF SL2S≠PHI THEN SL2←SL2S;SL2S←PHI;
	   IF SL3S≠PHI THEN SL3←SL3S;SL3S←PHI;
	   GO TO LOOP;

	END "FINDMATCH";

END "RECOG3";